package com.zjcloud.jwgl.service.impl;

import com.zjcloud.common.utils.DateUtils;
import com.zjcloud.common.utils.SecurityUtils;
import com.zjcloud.jwgl.domain.AcScheduleConstraintTemplate;
import com.zjcloud.jwgl.exception.TemplateValidationException;
import com.zjcloud.jwgl.mapper.AcScheduleConstraintTemplateMapper;
import com.zjcloud.jwgl.service.IAcTemplateAggregateService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 排课约束模板聚合服务实现类
 * 将模板作为聚合根，提供更高层次的业务接口
 * 
 * @author zjcloud
 * @date 2024-12-19
 */
@Service
public class AcTemplateAggregateServiceImpl implements IAcTemplateAggregateService {
    
    private static final Logger log = LoggerFactory.getLogger(AcTemplateAggregateServiceImpl.class);
    
    /** 标准约束条件数量 */
    private static final int STANDARD_CONSTRAINT_COUNT = 12;
    
    /** 标准约束条件类型映射 */
    private static final Map<String, String> STANDARD_CONSTRAINT_TYPES = new HashMap<>();
    
    static {
        STANDARD_CONSTRAINT_TYPES.put("1", "教师偏好约束");
        STANDARD_CONSTRAINT_TYPES.put("2", "教室容量约束");
        STANDARD_CONSTRAINT_TYPES.put("3", "课程冲突约束");
        STANDARD_CONSTRAINT_TYPES.put("4", "教师时间冲突约束");
        STANDARD_CONSTRAINT_TYPES.put("5", "班级时间冲突约束");
        STANDARD_CONSTRAINT_TYPES.put("6", "教室时间冲突约束");
        STANDARD_CONSTRAINT_TYPES.put("7", "连堂课约束");
        STANDARD_CONSTRAINT_TYPES.put("8", "教师工作量约束");
        STANDARD_CONSTRAINT_TYPES.put("9", "课程优先级约束");
        STANDARD_CONSTRAINT_TYPES.put("10", "特殊时间要求约束");
        STANDARD_CONSTRAINT_TYPES.put("11", "教室设备要求约束");
        STANDARD_CONSTRAINT_TYPES.put("12", "班级课程分布约束");
    }
    
    @Autowired
    private AcScheduleConstraintTemplateMapper templateMapper;
    
    /**
     * 获取完整的模板信息（包含所有约束条件）
     * 
     * @param templateName 模板名称
     * @return 模板约束条件列表
     * @throws TemplateValidationException 当模板不存在或不完整时抛出异常
     */
    @Override
    public List<AcScheduleConstraintTemplate> getCompleteTemplate(String templateName) throws TemplateValidationException {
        if (!StringUtils.hasText(templateName)) {
            throw new TemplateValidationException("INVALID_TEMPLATE_NAME", "模板名称不能为空", templateName);
        }
        
        // 检查模板是否存在
        if (!templateExists(templateName)) {
            throw new TemplateValidationException("TEMPLATE_NOT_FOUND", "模板不存在", templateName);
        }
        
        // 获取模板约束条件列表
        List<AcScheduleConstraintTemplate> templateList = templateMapper.selectByTemplateName(templateName);
        
        if (CollectionUtils.isEmpty(templateList)) {
            throw new TemplateValidationException("TEMPLATE_EMPTY", "模板数据为空", templateName);
        }
        
        // 验证模板完整性
        if (!validateTemplateIntegrity(templateName)) {
            int missingCount = templateMapper.checkTemplateIntegrity(templateName);
            throw new TemplateValidationException("TEMPLATE_INCOMPLETE", "模板不完整，缺少约束条件", templateName, missingCount);
        }
        
        log.info("成功获取完整模板: {}, 包含 {} 个约束条件", templateName, templateList.size());
        return templateList;
    }
    
    /**
     * 验证模板完整性
     * 
     * @param templateName 模板名称
     * @return 验证结果，true表示完整，false表示不完整
     * @throws TemplateValidationException 当验证失败时抛出异常
     */
    @Override
    public boolean validateTemplateIntegrity(String templateName) throws TemplateValidationException {
        if (!StringUtils.hasText(templateName)) {
            throw new TemplateValidationException("INVALID_TEMPLATE_NAME", "模板名称不能为空", templateName);
        }
        
        try {
            int missingCount = templateMapper.checkTemplateIntegrity(templateName);
            boolean isComplete = missingCount == 0;
            
            log.debug("模板 {} 完整性验证结果: {}, 缺失约束条件数量: {}", templateName, isComplete, missingCount);
            return isComplete;
        } catch (Exception e) {
            log.error("验证模板完整性时发生错误: {}", e.getMessage(), e);
            throw new TemplateValidationException("VALIDATION_ERROR", "验证模板完整性时发生错误: " + e.getMessage(), templateName);
        }
    }
    
    /**
     * 获取模板统计信息
     * 
     * @param templateName 模板名称
     * @return 统计信息映射
     */
    @Override
    public Map<String, Object> getTemplateStatistics(String templateName) {
        Map<String, Object> statistics = new HashMap<>();
        
        if (!StringUtils.hasText(templateName)) {
            statistics.put("error", "模板名称不能为空");
            return statistics;
        }
        
        try {
            // 获取基本统计信息
            AcScheduleConstraintTemplate stats = templateMapper.getTemplateStatistics(templateName);
            if (stats != null) {
                statistics.put("templateName", stats.getTemplateName());
                statistics.put("description", stats.getDescription());
                statistics.put("constraintCount", stats.getDefaultWeight()); // 这里复用了defaultWeight字段存储数量
                statistics.put("createTime", stats.getCreateTime());
                statistics.put("updateTime", stats.getUpdateTime());
            }
            
            // 获取完整性信息
            int missingCount = templateMapper.checkTemplateIntegrity(templateName);
            statistics.put("missingConstraints", missingCount);
            statistics.put("isComplete", missingCount == 0);
            statistics.put("completeness", String.format("%.1f%%", (STANDARD_CONSTRAINT_COUNT - missingCount) * 100.0 / STANDARD_CONSTRAINT_COUNT));
            
            // 获取约束条件类型列表
            List<String> constraintTypes = templateMapper.getTemplateConstraintTypes(templateName);
            statistics.put("constraintTypes", constraintTypes);
            
        } catch (Exception e) {
            log.error("获取模板统计信息时发生错误: {}", e.getMessage(), e);
            statistics.put("error", "获取统计信息失败: " + e.getMessage());
        }
        
        return statistics;
    }
    
    /**
     * 创建完整的模板（包含所有约束条件）
     * 
     * @param templateName 模板名称
     * @param description 模板描述
     * @param constraintConfigs 约束条件配置列表
     * @return 创建成功的记录数
     * @throws TemplateValidationException 当创建失败时抛出异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int createCompleteTemplate(String templateName, String description, List<Map<String, Object>> constraintConfigs) throws TemplateValidationException {
        if (!StringUtils.hasText(templateName)) {
            throw new TemplateValidationException("INVALID_TEMPLATE_NAME", "模板名称不能为空", templateName);
        }
        
        if (templateExists(templateName)) {
            throw new TemplateValidationException("TEMPLATE_EXISTS", "模板已存在", templateName);
        }
        
        if (CollectionUtils.isEmpty(constraintConfigs)) {
            throw new TemplateValidationException("INVALID_CONSTRAINTS", "约束条件配置不能为空", templateName);
        }
        
        try {
            List<AcScheduleConstraintTemplate> templateList = new ArrayList<>();
            String currentUser = SecurityUtils.getUsername();
            Date currentTime = DateUtils.getNowDate();
            
            for (int i = 0; i < constraintConfigs.size(); i++) {
                Map<String, Object> config = constraintConfigs.get(i);
                
                AcScheduleConstraintTemplate template = new AcScheduleConstraintTemplate();
                template.setTemplateName(templateName);
                template.setDescription(description);
                template.setConstraintName((String) config.get("constraintName"));
                template.setConstraintType((String) config.get("constraintType"));
                template.setDefaultWeight((Integer) config.get("defaultWeight"));
                template.setEnabled("1");
                template.setIsDefault("0");
                template.setSortOrder(i + 1);
                template.setCreateBy(currentUser);
                template.setCreateTime(currentTime);
                
                templateList.add(template);
            }
            
            int result = templateMapper.batchInsertTemplateConstraints(templateList);
            log.info("成功创建模板: {}, 插入 {} 条约束条件", templateName, result);
            return result;
            
        } catch (Exception e) {
            log.error("创建模板时发生错误: {}", e.getMessage(), e);
            throw new TemplateValidationException("CREATE_ERROR", "创建模板失败: " + e.getMessage(), templateName);
        }
    }
    
    /**
     * 复制模板
     * 
     * @param sourceTemplateName 源模板名称
     * @param targetTemplateName 目标模板名称
     * @param targetDescription 目标模板描述
     * @return 复制成功的记录数
     * @throws TemplateValidationException 当复制失败时抛出异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int copyTemplate(String sourceTemplateName, String targetTemplateName, String targetDescription) throws TemplateValidationException {
        if (!StringUtils.hasText(sourceTemplateName) || !StringUtils.hasText(targetTemplateName)) {
            throw new TemplateValidationException("INVALID_TEMPLATE_NAME", "源模板名称和目标模板名称不能为空", sourceTemplateName);
        }
        
        if (sourceTemplateName.equals(targetTemplateName)) {
            throw new TemplateValidationException("SAME_TEMPLATE_NAME", "源模板和目标模板名称不能相同", sourceTemplateName);
        }
        
        if (templateExists(targetTemplateName)) {
            throw new TemplateValidationException("TARGET_TEMPLATE_EXISTS", "目标模板已存在", targetTemplateName);
        }
        
        // 获取源模板
        List<AcScheduleConstraintTemplate> sourceTemplates = getCompleteTemplate(sourceTemplateName);
        
        try {
            List<AcScheduleConstraintTemplate> targetTemplates = new ArrayList<>();
            String currentUser = SecurityUtils.getUsername();
            Date currentTime = DateUtils.getNowDate();
            
            for (AcScheduleConstraintTemplate source : sourceTemplates) {
                AcScheduleConstraintTemplate target = new AcScheduleConstraintTemplate();
                target.setTemplateName(targetTemplateName);
                target.setDescription(targetDescription);
                target.setConstraintName(source.getConstraintName());
                target.setConstraintType(source.getConstraintType());
                target.setDefaultWeight(source.getDefaultWeight());
                target.setEnabled(source.getEnabled());
                target.setIsDefault("0"); // 复制的模板默认不是系统默认模板
                target.setSortOrder(source.getSortOrder());
                target.setCreateBy(currentUser);
                target.setCreateTime(currentTime);
                
                targetTemplates.add(target);
            }
            
            int result = templateMapper.batchInsertTemplateConstraints(targetTemplates);
            log.info("成功复制模板: {} -> {}, 复制 {} 条约束条件", sourceTemplateName, targetTemplateName, result);
            return result;
            
        } catch (Exception e) {
            log.error("复制模板时发生错误: {}", e.getMessage(), e);
            throw new TemplateValidationException("COPY_ERROR", "复制模板失败: " + e.getMessage(), sourceTemplateName);
        }
    }
    
    /**
     * 删除完整的模板（包含所有约束条件）
     * 
     * @param templateName 模板名称
     * @return 删除的记录数
     * @throws TemplateValidationException 当删除失败时抛出异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteCompleteTemplate(String templateName) throws TemplateValidationException {
        if (!StringUtils.hasText(templateName)) {
            throw new TemplateValidationException("INVALID_TEMPLATE_NAME", "模板名称不能为空", templateName);
        }
        
        if (!templateExists(templateName)) {
            throw new TemplateValidationException("TEMPLATE_NOT_FOUND", "模板不存在", templateName);
        }
        
        try {
            int result = templateMapper.deleteByTemplateName(templateName);
            log.info("成功删除模板: {}, 删除 {} 条约束条件", templateName, result);
            return result;
            
        } catch (Exception e) {
            log.error("删除模板时发生错误: {}", e.getMessage(), e);
            throw new TemplateValidationException("DELETE_ERROR", "删除模板失败: " + e.getMessage(), templateName);
        }
    }
    
    /**
     * 获取所有可用的模板名称列表
     * 
     * @return 模板名称列表
     */
    @Override
    public List<String> getAvailableTemplateNames() {
        try {
            List<AcScheduleConstraintTemplate> templates = templateMapper.selectAcScheduleConstraintTemplateList(new AcScheduleConstraintTemplate());
            return templates.stream()
                    .map(AcScheduleConstraintTemplate::getTemplateName)
                    .distinct()
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取可用模板名称列表时发生错误: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 检查模板是否存在
     * 
     * @param templateName 模板名称
     * @return 存在返回true，不存在返回false
     */
    @Override
    public boolean templateExists(String templateName) {
        if (!StringUtils.hasText(templateName)) {
            return false;
        }
        
        try {
            return templateMapper.validateTemplateExists(templateName) > 0;
        } catch (Exception e) {
            log.error("检查模板是否存在时发生错误: {}", e.getMessage(), e);
            return false;
        }
    }
    
    /**
     * 获取模板的约束条件类型列表
     * 
     * @param templateName 模板名称
     * @return 约束条件类型列表
     */
    @Override
    public List<String> getTemplateConstraintTypes(String templateName) {
        if (!StringUtils.hasText(templateName)) {
            return new ArrayList<>();
        }
        
        try {
            return templateMapper.getTemplateConstraintTypes(templateName);
        } catch (Exception e) {
            log.error("获取模板约束条件类型列表时发生错误: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 修复模板完整性（补充缺失的约束条件）
     * 
     * @param templateName 模板名称
     * @return 补充的约束条件数量
     * @throws TemplateValidationException 当修复失败时抛出异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int repairTemplateIntegrity(String templateName) throws TemplateValidationException {
        if (!StringUtils.hasText(templateName)) {
            throw new TemplateValidationException("INVALID_TEMPLATE_NAME", "模板名称不能为空", templateName);
        }
        
        if (!templateExists(templateName)) {
            throw new TemplateValidationException("TEMPLATE_NOT_FOUND", "模板不存在", templateName);
        }
        
        try {
            // 获取现有的约束条件类型
            List<String> existingTypes = getTemplateConstraintTypes(templateName);
            Set<String> existingTypeSet = new HashSet<>(existingTypes);
            
            // 找出缺失的约束条件类型
            List<String> missingTypes = STANDARD_CONSTRAINT_TYPES.keySet().stream()
                    .filter(type -> !existingTypeSet.contains(type))
                    .collect(Collectors.toList());
            
            if (missingTypes.isEmpty()) {
                log.info("模板 {} 已经完整，无需修复", templateName);
                return 0;
            }
            
            // 获取模板基本信息
            AcScheduleConstraintTemplate templateInfo = templateMapper.selectFirstByTemplateName(templateName);
            String description = templateInfo != null ? templateInfo.getDescription() : "修复后的模板";
            
            // 创建缺失的约束条件
            List<AcScheduleConstraintTemplate> missingConstraints = new ArrayList<>();
            String currentUser = SecurityUtils.getUsername();
            Date currentTime = DateUtils.getNowDate();
            
            for (String missingType : missingTypes) {
                AcScheduleConstraintTemplate constraint = new AcScheduleConstraintTemplate();
                constraint.setTemplateName(templateName);
                constraint.setDescription(description);
                constraint.setConstraintName(STANDARD_CONSTRAINT_TYPES.get(missingType));
                constraint.setConstraintType(missingType);
                constraint.setDefaultWeight(50); // 默认权重
                constraint.setEnabled("1");
                constraint.setIsDefault("0");
                constraint.setSortOrder(Integer.parseInt(missingType));
                constraint.setCreateBy(currentUser);
                constraint.setCreateTime(currentTime);
                
                missingConstraints.add(constraint);
            }
            
            int result = templateMapper.batchInsertTemplateConstraints(missingConstraints);
            log.info("成功修复模板 {} 的完整性，补充 {} 个约束条件", templateName, result);
            return result;
            
        } catch (Exception e) {
            log.error("修复模板完整性时发生错误: {}", e.getMessage(), e);
            throw new TemplateValidationException("REPAIR_ERROR", "修复模板完整性失败: " + e.getMessage(), templateName);
        }
    }
    
    /**
     * 批量验证多个模板的完整性
     * 
     * @param templateNames 模板名称列表
     * @return 验证结果映射，key为模板名称，value为验证结果
     */
    @Override
    public Map<String, Boolean> batchValidateTemplates(List<String> templateNames) {
        Map<String, Boolean> results = new HashMap<>();
        
        if (CollectionUtils.isEmpty(templateNames)) {
            return results;
        }
        
        for (String templateName : templateNames) {
            try {
                boolean isValid = validateTemplateIntegrity(templateName);
                results.put(templateName, isValid);
            } catch (Exception e) {
                log.error("验证模板 {} 时发生错误: {}", templateName, e.getMessage());
                results.put(templateName, false);
            }
        }
        
        return results;
    }
    
    /**
     * 获取模板的详细信息（用于展示）
     * 
     * @param templateName 模板名称
     * @return 模板详细信息
     */
    @Override
    public Map<String, Object> getTemplateDetails(String templateName) {
        Map<String, Object> details = new HashMap<>();
        
        if (!StringUtils.hasText(templateName)) {
            details.put("error", "模板名称不能为空");
            return details;
        }
        
        try {
            // 获取基本信息
            details.putAll(getTemplateStatistics(templateName));
            
            // 获取详细的约束条件列表
            List<AcScheduleConstraintTemplate> constraints = templateMapper.selectByTemplateName(templateName);
            details.put("constraints", constraints);
            
            // 添加约束条件详细信息
            Map<String, Object> constraintDetails = new HashMap<>();
            for (AcScheduleConstraintTemplate constraint : constraints) {
                Map<String, Object> constraintInfo = new HashMap<>();
                constraintInfo.put("name", constraint.getConstraintName());
                constraintInfo.put("weight", constraint.getDefaultWeight());
                constraintInfo.put("enabled", constraint.getEnabled());
                constraintInfo.put("sortOrder", constraint.getSortOrder());
                constraintDetails.put(constraint.getConstraintType(), constraintInfo);
            }
            details.put("constraintDetails", constraintDetails);
            
        } catch (Exception e) {
            log.error("获取模板详细信息时发生错误: {}", e.getMessage(), e);
            details.put("error", "获取详细信息失败: " + e.getMessage());
        }
        
        return details;
    }
}